package org.uu.mybatisplus.component;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.reflect.MethodSignature;
import org.uu.mybatisplus.annota.PrivacyKeyAnnotation;
import org.uu.mybatisplus.utils.ClassRecursionUtils;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;

public class PrivacyKeyAspect {
    /**
     * @Description: 环绕通知包含此注解的
     * @param: ProceedingJoinPoint joinPoint
     * @return: Object
     */
    @Around(value = "@annotation(\"aop注解地址xxxxx\")")
    public Object repeatSub(ProceedingJoinPoint joinPoint) throws Throwable {
        return joinPoint.proceed();
    }

    /**
     * @Description: 后置通知
     */
    @AfterReturning(value = "@annotation(\"aop注解地址\")",returning = "result")
    public void setPrivacyKeyType(JoinPoint joinPoint, Object result) throws Throwable {
        //进行注解 值获取
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //是否开启脱敏
        boolean flag = method.getDeclaredAnnotation(PrivacyKeyAnnotation.class).isKey();
        //是否对分页进行脱敏
        boolean status = method.getDeclaredAnnotation(PrivacyKeyAnnotation.class).isPageKey();
        if (!status) {
            //进行返回值反射
            Class<?> aClass = ClassRecursionUtils.getClass(result.getClass(), "isPrivacyKey");
            if (null != aClass) {
                setFieldMethod(result, flag, aClass);
            }
        } else {
            //反射分页page
            //反射list类型
            Parameter[] parameters = signature.getMethod().getParameters();
            //泛型名称
            String name = parameters[0].getName();
            //泛型class
            Class<?> type = parameters[0].getType();
            //包名
            String typeName = type.getName();
            PropertyDescriptor[] ps = Introspector.getBeanInfo(result.getClass(), Object.class).getPropertyDescriptors();
            for (PropertyDescriptor prop : ps) {
                if (prop.getPropertyType().isAssignableFrom(List.class)) { //List 集合类型
                    Object obj = result.getClass().getMethod(prop.getReadMethod().getName()).invoke(result);
                    if(obj !=null){
                        List<?> listObj = (List<?>) obj;
                        for (Object next : listObj) {
                            Class<?> classObj = Class.forName(typeName);
                            //获取成员变量
                            Class<?> keyClass = ClassRecursionUtils.getClass(classObj, "isPrivacyKey");
                            setFieldMethod(next, flag, keyClass);
                        }
                    }

                }
            }
        }
    }

    /**
     * 内容填充
     */
    private void setFieldMethod(Object result, boolean flag, Class<?> aClass) throws IllegalAccessException {
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field field : declaredFields) {
            //设置属性的可访问性
            field.setAccessible(true);
            //只获取isPrivacyKey
            String name = field.getName();
            //过滤非布尔类型
            Class<?> type = field.getType();
            //并且只添加 isPrivacyKey
            if (type.isAssignableFrom(Boolean.class) && "isPrivacyKey".equals(name)){
                //重新写入
                field.set(result,flag);
            }
        }
    }
}
